home *** CD-ROM | disk | FTP | other *** search
/ CD Classic 39 / CD CLASSIC #39 (1998).iso / EMPRESA / visio / Vistdstd / Install / Data.Z / Helpers.CPP < prev    next >
C/C++ Source or Header  |  1997-11-11  |  16KB  |  809 lines

  1. /*    HELPERS.CPP - Helper classes for easing BSTR and VARIANT use.
  2.  *  Copyright (C) 1996-1997 Visio Corporation. All rights reserved.
  3.  */
  4.  
  5. #ifdef MFC_HELPERS
  6. #include "stdafx.h"
  7. #endif
  8.  
  9. #include <windows.h>
  10. #include <ole2.h>
  11. #include <winnls.h>
  12. #include <tchar.h>
  13.  
  14. #include "helpers.h"
  15.  
  16.  
  17. //    ***************************************************************************
  18. //    The default BSTR helper class implementation:
  19.  
  20. #define V_MAX_STR_CONVERT 2048
  21.  
  22. static OLECHAR szOleStr[V_MAX_STR_CONVERT];
  23.  
  24. VBstr::VBstr()
  25. {
  26.     m_bstr= NULL;
  27. }
  28.  
  29. VBstr::VBstr(const VBstr FAR &other)
  30. {
  31.     m_bstr= SysAllocString(other.m_bstr);
  32. }
  33.  
  34. HRESULT VBstr::AllocFromLPCTSTR(LPCTSTR lpStr)
  35. {
  36.     if (lpStr)
  37.     {
  38. #ifndef OLE2ANSI
  39.         int nBytes= _tcslen(lpStr) + 1;
  40.         OLECHAR *pOleStr= szOleStr;
  41.  
  42.         if (nBytes > (ULONG)(V_MAX_STR_CONVERT))
  43.         {
  44.             pOleStr= new OLECHAR[nBytes];
  45.         }
  46.  
  47.         MultiByteToWideChar(GetACP(), MB_PRECOMPOSED, lpStr, -1, pOleStr, nBytes);
  48.         m_bstr= SysAllocString(pOleStr);
  49.  
  50.         if (nBytes > (ULONG)(V_MAX_STR_CONVERT))
  51.         {
  52.             delete [] pOleStr;
  53.         }
  54. #else
  55.         m_bstr= SysAllocString(lpStr);
  56. #endif
  57.     }
  58.  
  59.     return NOERROR;
  60. }
  61.  
  62. VBstr::VBstr(LPCTSTR lpStr)
  63. {
  64.     m_bstr= NULL;
  65.     AllocFromLPCTSTR(lpStr);
  66. }
  67.  
  68. VBstr::VBstr(BSTR bstr, BOOL bAssumeResponsibility /*= FALSE*/)
  69. {
  70.     //    *REQUIRED*
  71.     if (bAssumeResponsibility)
  72.         m_bstr= bstr;
  73.     else
  74.         m_bstr= SysAllocString(bstr);
  75. }
  76.  
  77. VBstr::~VBstr()
  78. {
  79.     if (m_bstr)
  80.         SysFreeString(m_bstr);
  81. }
  82.  
  83. VBstr::operator const BSTR() const
  84. {
  85.     //    *REQUIRED*
  86.     return m_bstr;
  87. }
  88.  
  89. const VBstr FAR &VBstr::operator=(const BSTR bstr)
  90. {
  91.     //    *REQUIRED*
  92.     if (m_bstr)
  93.         SysFreeString(m_bstr);
  94.     m_bstr= SysAllocString(bstr);
  95.     return (*this);
  96. }
  97.  
  98. const VBstr FAR &VBstr::operator=(const VBstr &other)
  99. {
  100.     if (m_bstr)
  101.         SysFreeString(m_bstr);
  102.     m_bstr= SysAllocString(other.m_bstr);
  103.     return (*this);
  104. }
  105.  
  106. const VBstr FAR &VBstr::operator=(LPCTSTR lpStr)
  107. {
  108.     if (m_bstr)
  109.         SysFreeString(m_bstr);
  110.     m_bstr= NULL;
  111.     AllocFromLPCTSTR(lpStr);
  112.     return (*this);
  113. }
  114.  
  115. const VBstr FAR &VBstr:: operator=(LPCOLESTR lpOlestr)
  116. {
  117.     if (m_bstr)
  118.         SysFreeString(m_bstr);
  119.     m_bstr= SysAllocString(lpOlestr);
  120.     return (*this);
  121. }
  122.  
  123.  
  124. #define VBSTR_COMPARE        wcscmp
  125. #define VBSTR_COMPARE_I        _wcsicmp
  126.  
  127.  
  128. //    Since Borland 5.0 doesn't support wcscmp and Win95 only
  129. //    stubs lstrcmpW, write our own:
  130. #ifdef __BORLANDC__
  131.  
  132.     //    Neither of these will work with embedded NULL OLECHARs:
  133.     //        (but for simple string compares, it's better than nothing...)
  134.     int VBstr_cmp(unsigned short *s1, unsigned short *s2)
  135.     {
  136.         int ret;
  137.  
  138.         ret= (int)((short)*s1 - (short)*s2);
  139.         while( (0==ret) && *s2)
  140.                 ++s1, ++s2, ret= (int)((short)*s1 - (short)*s2);
  141.  
  142.         return ret;
  143.     }
  144.  
  145.     //    For characters outside the A to Z range, this function compares them
  146.     //    exactly; watch out for strings with special accented characters - you may
  147.     //    have to write your own version of this for certain applications with the
  148.     //    Borland compiler...
  149.     //        (but again, for simple string compares, it's better than nothing...)
  150.     int VBstr_cmpi(unsigned short *s1, unsigned short *s2)
  151.     {
  152.         wchar_t f,l;
  153.  
  154.         do  {
  155.             f = ((*s1 <= L'Z') && (*s1 >= L'A'))
  156.                 ? *s1 + L'a' - L'A'
  157.                 : *s1;
  158.             l = ((*s2 <= L'Z') && (*s2 >= L'A'))
  159.                 ? *s2 + L'a' - L'A'
  160.                 : *s2;
  161.             s1++;
  162.             s2++;
  163.         } while ( (f) && (f == l) );
  164.  
  165.         return (int)(f - l);
  166.     }
  167.  
  168. #undef VBSTR_COMPARE
  169. #define VBSTR_COMPARE(s1, s2)        \
  170.         VBstr_cmp((unsigned short *)(s1), (unsigned short *)(s2))
  171.  
  172. #undef VBSTR_COMPARE_I
  173. #define VBSTR_COMPARE_I(s1, s2)        \
  174.         VBstr_cmpi((unsigned short *)(s1), (unsigned short *)(s2))
  175.  
  176. #endif
  177.  
  178.  
  179. BOOL VBstr::Compare(const VBstr FAR &other, BOOL bCaseSensitive /*= TRUE*/) const
  180. {
  181.     //    Use "vbstr.Compare(other, VBSTR_CASE_INSENSITIVE)" for case-insensitive compare...
  182.     //    Use "vbstr.Compare(other)" for case-sensitive compare...
  183.  
  184.     //    Simple string comparison function.
  185.     //    Only works on simple NULL terminated strings.
  186.     //    If you embed NULL OLECHARs within you BSTRs,
  187.     //    write another function to compare them.
  188.     //    The strings must be identical or
  189.     //    both NULL/"empty" to return TRUE.
  190.  
  191.     if (NULL==m_bstr)
  192.     {
  193.         if (NULL==other.m_bstr || 0==other.m_bstr[0])
  194.         {
  195.             //    They are both the "empty"/NULL string:
  196.             return TRUE;
  197.         }
  198.         else
  199.         {
  200.             //    One's NULL, but the other is non-NULL with content:
  201.             return FALSE;
  202.         }
  203.     }
  204.  
  205.     if (NULL==other.m_bstr)
  206.     {
  207.         if (0==m_bstr[0])
  208.         {
  209.             //    They are both the "empty"/NULL string:
  210.             return TRUE;
  211.         }
  212.         else
  213.         {
  214.             //    One's NULL, but the other is non-NULL with content:
  215.             return FALSE;
  216.         }
  217.     }
  218.  
  219.     //    They're both non-NULL, compare:
  220.     if (bCaseSensitive)
  221.     {
  222.         return (0==VBSTR_COMPARE(m_bstr, other.m_bstr));
  223.     }
  224.     else
  225.     {
  226.         return (0==VBSTR_COMPARE_I(m_bstr, other.m_bstr));
  227.     }
  228. }
  229.  
  230. BOOL VBstr::operator==(const VBstr FAR &other) const
  231. {
  232.     //    Case-sensitive!
  233.     //    Use "vbstr.Compare(other, VBSTR_CASE_INSENSITIVE)" for case-insensitive compare...
  234.     return Compare(other);
  235. }
  236.  
  237. #ifdef MFC_HELPERS
  238. void VBstr::ConvertToCString(CString FAR& cstr)
  239. {
  240.     if (m_bstr)
  241.     {
  242. #if defined(_WIN32) && !defined(OLE2ANSI)
  243.         int    nbyte= WideCharToMultiByte(GetACP(), 0, m_bstr, -1, NULL, 0, 0, 0);
  244.         LPTSTR lpStr= cstr.GetBuffer(nbyte);
  245.         WideCharToMultiByte(GetACP(), 0, m_bstr, -1, lpStr, nbyte, 0, 0);
  246.         cstr.ReleaseBuffer();
  247. #else
  248.         cstr= m_bstr;
  249. #endif
  250.     }
  251.     else
  252.     {
  253.         cstr = "";
  254.     }
  255. }
  256. #endif
  257.  
  258. HRESULT VBstr::ConvertToLPTSTR(LPTSTR pStr, ULONG *pnBytes)
  259. {
  260.     //    *pnBytes should be size of pStr buffer on entry
  261.     //    *pnBytes is size needed if E_FAIL is returned
  262.     //    *pnBytes is size copied if NOERROR is returned
  263.  
  264.     //    It is a BAD programming error to call this function with NULL args.
  265.     //    Don't do it!
  266.  
  267.     //    ASSERT(pStr!=NULL);
  268.     //    ASSERT(pnBytes!=NULL);
  269.  
  270.     int    nNeeded;    //    intentionally uninitialized - all code paths
  271.                     //    below initialize nNeeded properly
  272.  
  273.     if (m_bstr)
  274.     {
  275. #if defined(_WIN32) && !defined(OLE2ANSI)
  276.         nNeeded= WideCharToMultiByte(GetACP(), 0, m_bstr, -1, NULL, 0, 0, 0);
  277.  
  278.         if ( (*pnBytes) >= ((ULONG)nNeeded) )
  279.         {
  280.             WideCharToMultiByte(GetACP(), 0, m_bstr, -1, pStr, nNeeded, 0, 0);
  281.         }
  282.         else
  283.         {
  284.             (*pnBytes)= (ULONG) nNeeded;
  285.             return E_FAIL;
  286.         }
  287. #else
  288.         nNeeded= _tcslen(m_bstr) + 1;
  289.  
  290.         if ( (*pnBytes) >= ((ULONG)nNeeded) )
  291.         {
  292.             _tcscpy(pStr, m_bstr);
  293.         }
  294.         else
  295.         {
  296.             (*pnBytes)= (ULONG) nNeeded;
  297.             return E_FAIL;
  298.         }
  299. #endif
  300.     }
  301.     else
  302.     {
  303.         nNeeded= 1;
  304.  
  305.         if ( (*pnBytes) >= ((ULONG)nNeeded) )
  306.         {
  307.             (*pStr)= (TCHAR) 0;
  308.         }
  309.         else
  310.         {
  311.             (*pnBytes)= 1;
  312.             return E_FAIL;
  313.         }
  314.     }
  315.  
  316.     (*pnBytes)= (ULONG) nNeeded;
  317.  
  318.     return NOERROR;
  319. }
  320.  
  321.  
  322. //    ***************************************************************************
  323. //    The default VARIANT helper class implementation:
  324.  
  325. VVariant::VVariant()
  326. {
  327.     Init();
  328. }
  329.  
  330. VVariant::VVariant(const VVariant& other)
  331. {
  332.     Init();
  333.     Copy(other.m_v);
  334. }
  335.  
  336. VVariant::VVariant(const VARIANT& v)
  337. {
  338.     //    *REQUIRED*
  339.     Init();
  340.     Copy(v);
  341. }
  342.  
  343. VVariant::VVariant(LPCTSTR p)
  344. {
  345.     Init();
  346.     V_VT(&m_v)= VT_BSTR;
  347.     V_BSTR(&m_v)= SysAllocString(VBstr(p));
  348. }
  349.  
  350. VVariant::VVariant(const BSTR bstr, BOOL bAssumeResponsibility /*= FALSE*/)
  351. {
  352.     Init();
  353.     V_VT(&m_v)= VT_BSTR;
  354.  
  355.     if (bAssumeResponsibility)
  356.         V_BSTR(&m_v)= bstr;
  357.     else
  358.         V_BSTR(&m_v)= SysAllocString(bstr);
  359. }
  360.  
  361. VVariant::VVariant(const long n)
  362. {
  363.     Init();
  364.     V_VT(&m_v)= VT_I4;
  365.     V_I4(&m_v)= n;
  366. }
  367.  
  368. VVariant::VVariant(const double d)
  369. {
  370.     Init();
  371.     V_VT(&m_v)= VT_R8;
  372.     V_R8(&m_v)= d;
  373. }
  374.  
  375. VVariant::VVariant(const LPUNKNOWN pUnk)
  376. {
  377.     Init();
  378.     V_VT(&m_v)= VT_UNKNOWN;
  379.     V_UNKNOWN(&m_v)= pUnk;
  380.     if (pUnk)
  381.         pUnk->AddRef();
  382. }
  383.  
  384. VVariant::VVariant(const LPDISPATCH pDisp)
  385. {
  386.     Init();
  387.     V_VT(&m_v)= VT_DISPATCH;
  388.     V_DISPATCH(&m_v)= pDisp;
  389.     if (pDisp)
  390.         pDisp->AddRef();
  391. }
  392.  
  393. VVariant::~VVariant()
  394. {
  395.     Clear();
  396. }
  397.  
  398.  
  399. VVariant::operator VARIANT *()
  400. {
  401.     //    *REQUIRED*
  402.     return &m_v;
  403. }
  404.  
  405. VVariant::operator VARIANT()
  406. {
  407.     //    *REQUIRED*
  408.     return m_v;
  409. }
  410.  
  411. VVariant::operator const VARIANT() const
  412. {
  413.     //    *REQUIRED*
  414.     return m_v;
  415. }
  416.  
  417. const VVariant& VVariant::operator=(const VVariant& other)
  418. {
  419.     Clear();
  420.     Copy(other.m_v);
  421.     return (*this);
  422. }
  423.  
  424. const VVariant& VVariant::operator=(const VARIANT& v)
  425. {
  426.     Clear();
  427.     Copy(v);
  428.     return (*this);
  429. }
  430.  
  431. const VVariant& VVariant::operator=(LPCTSTR p)
  432. {
  433.     Clear();
  434.     V_VT(&m_v)= VT_BSTR;
  435.     V_BSTR(&m_v)= SysAllocString(VBstr(p));
  436.     return (*this);
  437. }
  438.  
  439. const VVariant& VVariant::operator=(const BSTR bstr)
  440. {
  441.     Clear();
  442.     V_VT(&m_v)= VT_BSTR;
  443.     V_BSTR(&m_v)= SysAllocString(bstr);
  444.     return (*this);
  445. }
  446.  
  447. const VVariant& VVariant::operator=(const long n)
  448. {
  449.     Clear();
  450.     V_VT(&m_v)= VT_I4;
  451.     V_I4(&m_v)= n;
  452.     return (*this);
  453. }
  454.  
  455. const VVariant& VVariant::operator=(const double d)
  456. {
  457.     Clear();
  458.     V_VT(&m_v)= VT_R8;
  459.     V_R8(&m_v)= d;
  460.     return (*this);
  461. }
  462.  
  463. const VVariant& VVariant::operator=(const LPUNKNOWN pUnk)
  464. {
  465.     Clear();
  466.     V_VT(&m_v)= VT_UNKNOWN;
  467.     V_UNKNOWN(&m_v)= pUnk;
  468.     if (pUnk)
  469.         pUnk->AddRef();
  470.     return (*this);
  471. }
  472.  
  473. const VVariant& VVariant::operator=(const LPDISPATCH pDisp)
  474. {
  475.     Clear();
  476.     V_VT(&m_v)= VT_DISPATCH;
  477.     V_DISPATCH(&m_v)= pDisp;
  478.     if (pDisp)
  479.         pDisp->AddRef();
  480.     return (*this);
  481. }
  482.  
  483. void VVariant::Init(void)
  484. {
  485.     VariantInit(&m_v);
  486. }
  487.  
  488. void VVariant::Clear(void)
  489. {
  490.     VariantClear(&m_v);
  491. }
  492.  
  493. void VVariant::Copy(const VARIANT &v)
  494. {
  495.     VariantCopy(&m_v, (VARIANT *) &v);
  496. }
  497.  
  498.  
  499. //    ***************************************************************************
  500. //    Generalized SAFEARRAY helper class implementation:
  501.  
  502. HRESULT VSafeArray::Init(void)
  503. {
  504.     //    This Init must be called before Create. Calling it after Create
  505.     //    would cause a memory leak...
  506.  
  507.     //    We have it so we don't duplicate a bunch of code in all the various
  508.     //    constructors.... Set initial values of members here.
  509.  
  510.     //    Call from ALL constructors...
  511.  
  512.     m_nDims= DIM_UNINITIALIZED;
  513.     m_vt= VT_EMPTY;
  514.     m_pSA= NULL;
  515.  
  516.     return NOERROR;
  517. }
  518.  
  519. VSafeArray::VSafeArray()
  520. {
  521.     Init();
  522. }
  523.  
  524. VSafeArray::VSafeArray(VARTYPE vt, unsigned int nDims, SAFEARRAYBOUND FAR* pBounds)
  525. {
  526.     //    Generic:
  527.     Init();
  528.     Create(vt, nDims, pBounds);
  529. }
  530.  
  531. VSafeArray::VSafeArray(VARTYPE vt, ULONG cElements, LONG lLbound)
  532. {
  533.     //    Simple 1D:
  534.     SAFEARRAYBOUND bound[1];
  535.     bound[0].cElements= cElements;
  536.     bound[0].lLbound= lLbound;
  537.  
  538.     Init();
  539.     Create(vt, 1, bound);
  540. }
  541.  
  542. VSafeArray::VSafeArray(VARTYPE vt, ULONG cElements1, LONG lLbound1, ULONG cElements2, LONG lLbound2)
  543. {
  544.     //    2D:
  545.     SAFEARRAYBOUND bound[2];
  546.     bound[0].cElements= cElements1;
  547.     bound[0].lLbound= lLbound1;
  548.     bound[1].cElements= cElements2;
  549.     bound[1].lLbound= lLbound2;
  550.  
  551.     Init();
  552.     Create(vt, 2, bound);
  553. }
  554.  
  555. VSafeArray::VSafeArray(VARTYPE vt, ULONG cElements1, LONG lLbound1, ULONG cElements2, LONG lLbound2, ULONG cElements3, LONG lLbound3)
  556. {
  557.     //    3D:
  558.     SAFEARRAYBOUND bound[3];
  559.     bound[0].cElements= cElements1;
  560.     bound[0].lLbound= lLbound1;
  561.     bound[1].cElements= cElements2;
  562.     bound[1].lLbound= lLbound2;
  563.     bound[2].cElements= cElements3;
  564.     bound[2].lLbound= lLbound3;
  565.  
  566.     Init();
  567.     Create(vt, 3, bound);
  568. }
  569.  
  570. VSafeArray::~VSafeArray()
  571. {
  572.     Destroy();
  573. }
  574.  
  575. HRESULT VSafeArray::Create(VARTYPE vt, unsigned int nDims, SAFEARRAYBOUND FAR* pBounds)
  576. {
  577.     HRESULT hr= NOERROR;
  578.  
  579.     Destroy();    //    Forget about anything we currently point to...
  580.  
  581.     m_nDims= nDims;
  582.     m_vt= vt;
  583.     m_pSA= SafeArrayCreate(vt, nDims, pBounds);
  584.  
  585.     if (NULL==m_pSA)
  586.         hr= E_OUTOFMEMORY;
  587.  
  588.     return hr;
  589. }
  590.  
  591. HRESULT VSafeArray::Destroy(void)
  592. {
  593.     HRESULT hr= NOERROR;
  594.  
  595.     if (NULL!=m_pSA)
  596.     {
  597.         hr= SafeArrayDestroy(m_pSA);
  598.         m_pSA= NULL;
  599.     }
  600.  
  601.     return hr;
  602. }
  603.  
  604. //****************************************************************************
  605.  
  606. unsigned int VSafeArray::GetDimensions(void)
  607. {
  608.     if (DIM_UNINITIALIZED==m_nDims && NULL!=m_pSA)
  609.     {
  610.         m_nDims= SafeArrayGetDim(m_pSA);
  611.     }
  612.  
  613.     return m_nDims;
  614. }
  615.  
  616. long VSafeArray::GetNumberElements(unsigned int nDim /*= 1*/)
  617. {
  618.     return GetUpper(nDim)-GetLower(nDim)+1;
  619. }
  620.  
  621. long VSafeArray::GetLower(unsigned int nDim /*= 1*/)
  622. {
  623.     long nRet= 0;
  624.  
  625.     if (DIM_UNINITIALIZED!=nDim && NULL!=m_pSA)
  626.     {
  627.         long nLower= 0;
  628.         if (SUCCEEDED(SafeArrayGetLBound(m_pSA, nDim, &nLower)))
  629.         {
  630.             nRet= nLower;
  631.         }
  632.     }
  633.  
  634.     return nRet;
  635. }
  636.  
  637. long VSafeArray::GetUpper(unsigned int nDim /*= 1*/)
  638. {
  639.     long nRet= 0;
  640.  
  641.     if (DIM_UNINITIALIZED!=nDim && NULL!=m_pSA)
  642.     {
  643.         long nUpper= 0;
  644.         if (SUCCEEDED(SafeArrayGetUBound(m_pSA, nDim, &nUpper)))
  645.         {
  646.             nRet= nUpper;
  647.         }
  648.     }
  649.  
  650.     return nRet;
  651. }
  652.  
  653. HRESULT VSafeArray::PutElement(long *pnIndices, void const *pData)
  654. {
  655.     HRESULT hr= E_FAIL;
  656.  
  657.     if (NULL!=m_pSA)
  658.     {
  659.         hr= SafeArrayPutElement(m_pSA, pnIndices, (void *) pData);
  660.     }
  661.  
  662.     return hr;
  663. }
  664.  
  665. HRESULT VSafeArray::GetElement(long *pnIndices, void *pData)
  666. {
  667.     HRESULT hr= E_FAIL;
  668.  
  669.     if (NULL!=m_pSA)
  670.     {
  671.         hr= SafeArrayGetElement(m_pSA, pnIndices, pData);
  672.     }
  673.  
  674.     return hr;
  675. }
  676.  
  677. VSafeArray::operator SAFEARRAY FAR* const (void) const
  678. {
  679.     return m_pSA;
  680. }
  681.  
  682. VSafeArray::operator SAFEARRAY FAR* FAR* (void) const
  683. {
  684.     return (SAFEARRAY FAR* FAR*) &m_pSA;
  685. }
  686.  
  687. SAFEARRAY FAR* FAR* VSafeArray::LPLPSAFEARRAY(void)
  688. {
  689.     //    Call this function when you are passing the SAFEARRAY ** to a method
  690.     //    which is going to fill in the SAFEARRAY for you. ('out' args)
  691.     Destroy();
  692.     return &m_pSA;
  693. }
  694.  
  695.  
  696. //    ***************************************************************************
  697. //    1-dimensional concrete SAFEARRAY helper class implementation:
  698.  
  699. HRESULT VSafeArray1D::PutShort(long nIndex, short n)
  700. {
  701.     //    ASSERT(VT_I2==m_vt);
  702.     return PutElement(&nIndex, &n);
  703. }
  704.  
  705. HRESULT VSafeArray1D::PutLong(long nIndex, long n)
  706. {
  707.     //    ASSERT(VT_I4==m_vt);
  708.     return PutElement(&nIndex, &n);
  709. }
  710.  
  711. HRESULT VSafeArray1D::PutDouble(long nIndex, double d)
  712. {
  713.     //    ASSERT(VT_R8==m_vt);
  714.     return PutElement(&nIndex, &d);
  715. }
  716.  
  717. HRESULT VSafeArray1D::PutBstr(long nIndex, BSTR bstr)
  718. {
  719.     //    ASSERT(VT_BSTR==m_vt);
  720.     return PutElement(&nIndex, bstr);
  721. }
  722.  
  723. HRESULT VSafeArray1D::PutVariant(long nIndex, const VARIANT &v)
  724. {
  725.     //    ASSERT(VT_VARIANT==m_vt);
  726.     return PutElement(&nIndex, &v);
  727. }
  728.  
  729. HRESULT VSafeArray1D::PutObject(long nIndex, LPUNKNOWN pUnk)
  730. {
  731.     //    ASSERT(VT_UNKNOWN==m_vt || VT_DISPATCH==m_vt);
  732.     return PutElement(&nIndex, pUnk);
  733. }
  734.  
  735. short VSafeArray1D::GetShort(long nIndex)
  736. {
  737.     short n= 0;
  738.     //    ASSERT(VT_I2==m_vt);
  739.     if (FAILED(GetElement(&nIndex, &n)))
  740.     {
  741.         n= -1;
  742.     }
  743.     return n;
  744. }
  745.  
  746. long VSafeArray1D::GetLong(long nIndex)
  747. {
  748.     long n= 0L;
  749.     //    ASSERT(VT_I4==m_vt);
  750.     if (FAILED(GetElement(&nIndex, &n)))
  751.     {
  752.         n= -1L;
  753.     }
  754.     return n;
  755. }
  756.  
  757. double VSafeArray1D::GetDouble(long nIndex)
  758. {
  759.     double d= 0.0;
  760.     //    ASSERT(VT_R8==m_vt);
  761.     if (FAILED(GetElement(&nIndex, &d)))
  762.     {
  763.         d= -1.0;
  764.     }
  765.     return d;
  766. }
  767.  
  768. BSTR VSafeArray1D::GetBstr(long nIndex)
  769. {
  770.     BSTR bstr= NULL;
  771.     //    ASSERT(VT_BSTR==m_vt);
  772.     if (FAILED(GetElement(&nIndex, &bstr)))
  773.     {
  774.         bstr= NULL;
  775.     }
  776.     //    non-NULL return MUST be SysFreeStringed
  777.     return bstr;
  778. }
  779.  
  780. VARIANT VSafeArray1D::GetVariant(long nIndex)
  781. {
  782.     VARIANT v;
  783.     //    ASSERT(VT_VARIANT==m_vt);
  784.     VariantInit(&v);
  785.     if (FAILED(GetElement(&nIndex, &v)))
  786.     {
  787.         V_VT(&v)= VT_EMPTY;
  788.         V_NONE(&v)= 0;
  789.     }
  790.     //    return MUST be VariantCleared
  791.     return v;
  792. }
  793.  
  794. LPUNKNOWN VSafeArray1D::GetObject(long nIndex)
  795. {
  796.     LPUNKNOWN pUnk= NULL;
  797.     //    ASSERT(VT_UNKNOWN==m_vt || VT_DISPATCH==m_vt);
  798.     if (FAILED(GetElement(&nIndex, &pUnk)))
  799.     {
  800.         pUnk= NULL;
  801.     }
  802.     else
  803.     {
  804.         pUnk->AddRef();
  805.         //    non-NULL return MUST be Released...
  806.     }
  807.     return pUnk;
  808. }
  809.